﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Collections;
using System.Globalization;

namespace WPCoco.Helpers
{
    public static class ReflectionHelper
    {
        public static Type[] TypesForInterface(Type it) 
        {
            Assembly a = Assembly.GetExecutingAssembly();
            Type[] types = a.GetTypes();
            List<Type> list = new List<Type>();
            foreach (Type t in types)
            {
                if (t.IsInterface) continue;
                if (it.IsAssignableFrom(t))
                    list.Add(t);
            }
            Type[] array = new Type[list.Count];
            list.CopyTo(array);
            return array;
        }

        public static Type[] TypesForAbstractClas(Type it)
        {
            Assembly a = Assembly.GetCallingAssembly();
            Type[] types = a.GetTypes();
            List<Type> list = new List<Type>();
            foreach (Type t in types)
            {
                if (t.IsAbstract) continue;
                if (it.IsAssignableFrom(t))
                    list.Add(t);
            }
            Type[] array = new Type[list.Count];
            list.CopyTo(array);
            return array;
        }

        public static bool SetValue(object o, string property, object value) 
        {
            Type t = o.GetType();
            PropertyInfo p = t.GetProperty(property);
            if (p == null || !p.CanWrite) return false;
            try
            {
                p.SetValue(o, value, null);
            }
            catch 
            {
                return false;
            }
            return true;
        }

        public static bool IsInteger(Type t)
        {
            return (t == typeof(int) || t == typeof(short) || t == typeof(byte) || t == typeof(long) ||
                    t == typeof(uint) || t == typeof(ushort) || t == typeof(sbyte) || t == typeof(ulong));
        }

        public static bool IsReal(Type t)
        {
            return (t == typeof(double) || t == typeof(float));
        }

        public static string GetRealValue(object o)
        {
            if (o is double) return ((double)o).ToString(CultureInfo.InvariantCulture);
            if (o is float) return ((float)o).ToString(CultureInfo.InvariantCulture);
            return string.Empty;
        }

        public static bool IsBool(Type t)
        {
            return t == typeof(bool);
        }

        public static bool IsString(Type t)
        {
            return t == typeof(string);
        }

        public static bool IsDateTime(Type t)
        {
            return t == typeof(DateTime);
        }

        public static bool IsDictionaryStringObject(Type t)
        {
            Type t2 = typeof(IDictionary<string, object>);
            return t2.IsAssignableFrom(t);
        }

        public static bool IsArray(Type t)
        {
            return t.IsArray;
        }

        public static bool IsEnumerable(Type t) 
        {
            return t.IsAssignableFrom(typeof(IEnumerable));
        }

        public static Dictionary<string, object> ConvertInstanceToDictionary(object obj)
        {
            Dictionary<string, object> dict = new Dictionary<string, object>();
            Type t = obj.GetType();
            PropertyInfo[] props = t.GetProperties(BindingFlags.Public | BindingFlags.SetField | BindingFlags.GetField | BindingFlags.Instance);
            object value;
            ParameterInfo[] par;
            foreach (PropertyInfo p in props)
            {
                par = p.GetIndexParameters();
                if (par.Length != 0) continue;
                value = p.GetValue(obj, null);

                if (IsInteger(p.PropertyType) || IsReal(p.PropertyType) || IsString(p.PropertyType) || IsBool(p.PropertyType))
                    dict[p.Name] = value;
                else
                    dict[p.Name] = ConvertInstanceToDictionary(value);                
            }
            return dict;
        }

    }
}
